import java.util.Scanner;

public class text{
    public static void main(String[] args) {
        Control control = new Control();
        control.FCFS();
        System.out.println("\n\n");
        control.SJF();
        System.out.println("\n\n");
        control.HRRF();
    }
}


class Control {
    private JCB job[];
    private int timeSimulator = 0;//时间模拟器

    class JCB {
        //由于是单道系统，所以每个作业的资源一定可以的到满足，所以不需要所需进程数，否则要定义 int sourceRequire
        StringBuffer name = new StringBuffer("");//作业名
        boolean beenFinished;//判断是否已经完成
        int enterSystemTime;//进入输入井的时间
        int beginWorkTime;//进入cpu的时间
        int runTime;//运行所需要的时间
        int finishTime;//完成时间
        int totalTime;//周转时间
        double weightTotalTime;//带权周转时间
        double responseRate=0;//响应比
    }

    //初始化
    public void initial() {
        System.out.println("JOB表初始化中");
        System.out.println("请问你要创建几个进程？");
        Scanner sc = new Scanner(System.in);
        int size = sc.nextInt();
        job = new JCB[size];
        for (int i = 0; i < size; i++) {
            job[i] = new JCB();

        }
        timeSimulator = 0;
        for (int i = 0; i < size; i++) {
            job[i].name.append("JOB" + (i + 1)); //给该进程命名
            System.out.println("请输入JOB" + (i + 1) + "进入系统的时间（即先后顺序）");
            job[i].enterSystemTime = sc.nextInt();
            System.out.println("请输入JOB" + (i + 1) + "所需要的运行时间（即作业长短）");
            job[i].runTime = sc.nextInt();
            job[i].beenFinished=false;
        }
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        try {
            Thread.sleep(15);//使当前线程休眠，进入阻塞状态（暂停执行），如果线程在睡眠状态被中断，将会抛出InterruptedException中断异常
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n初始化成功！");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\n");
    }

    //计算第i个job周转时间
    public void totalTime(int i) {
        job[i].totalTime = job[i].finishTime - job[i].enterSystemTime;
    }

    //计算第i个job平均周转时间
    public void calcWeightTotalTime(int i) {
        job[i].weightTotalTime = job[i].totalTime * 1.0 / job[i].runTime;
    }

    //所有作业的带权周转时间
    public double calcWeightTotalTime() {
        double sum = 0;
        for (int i = 0; i < job.length; i++) {
            sum += job[i].weightTotalTime;
        }
        return sum;
    }

    //所有作业的平均带权周转时间
    public double avgWeightTotalTime() {
        double sum = 0;
        for (int i = 0; i < job.length; i++) {
            sum += job[i].weightTotalTime;
        }
        return sum * 1.0 / job.length;
    }

    //所有作业的总周转时间
    public double calcTotalTime() {
        double sum = 0;
        for (int i = 0; i < job.length; i++) {
            sum += job[i].totalTime;
        }
        return sum;
    }

    //所有作业的平均周转时间
    public double avgTotalTime() {
        double sum = 0;
        for (int i = 0; i < job.length; i++) {
            sum += job[i].totalTime;
        }
        return sum * 1.0 / job.length;
    }

    //对作业表和调度表进行打印输出
    public void printWork() {
        System.out.println("作业名\t进入时间\t运行时间\t开始时间\t结束时间\t周转时间\t带权周转时间\t");
        for (int i = 0; i < job.length; i++) {
            System.out.println(" " + job[i].name + "\t" + " " + job[i].enterSystemTime + "\t\t" + " " + job[i].runTime + "\t\t"
                    + " " + job[i].beginWorkTime + "\t" + " " + job[i].finishTime + "\t" + " " + job[i].totalTime + "\t" + " " + job[i]. weightTotalTime+ "\t\t");
        }
        System.out.println("作业总周转时间" + "\t\t" + calcTotalTime() + "\n" + "作业总周转时间" + "\t\t"+calcWeightTotalTime());
        System.out.println("平均周转时间" + "\t\t" + avgTotalTime() + "\n" + "作业平均带权周转时间" + "\t\t" + avgWeightTotalTime());
    }


    //先来先服务算法
    public void FCFS() {
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        System.out.println("先来先服务调度算法（FCFS调度算法）");
        initial();//初始化
        for (int i = 0; i < job.length; i++) {
            System.out.println(job[i].name + "开始执行...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            job[i].beginWorkTime = timeSimulator;
            job[i].finishTime = job[i].beginWorkTime + job[i].runTime;
            timeSimulator = job[i].finishTime;
            totalTime(i);
            calcWeightTotalTime(i);
            System.out.println(job[i].name + "执行结束...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("\t\t\t\t FCFS调度算法运行结果");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        printWork();
    }

    //找到最短作业
    public int findMinJob() {
        int min = -1;
        int i;
        //找出第一个没有被执行过的作业
        for (i = 0; i < job.length; i++) {
            if (job[i].beenFinished == false && job[i].enterSystemTime <= timeSimulator) {
                min = i;
                break;
            }
        }
        //与第一个未被执行的作业对比，找出最小值
        for (int j = i; j < job.length; j++) {
            if (job[j].beenFinished == true) {
                continue;
            }
            if (job[j].runTime < job[min].runTime && job[j].enterSystemTime <= timeSimulator) {
                min = j;
            }
        }
        return min;
    }

    //短作业优先算法
    //步骤：1、找到等待中的最短作业 2、执行找到的最短作业 3、循环以上操作，直到所有作业被执行
    public void SJF() {
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        System.out.println("短作业调度算法（SJF调度算法）");
        initial();//初始化
        int minJob = 0;//开始短作业为0
        for (int i = 0; i < job.length; i++) {
            minJob = findMinJob();//找到目前的最短作业
            System.out.println(job[minJob].name+"开始执行...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            job[minJob].beginWorkTime = timeSimulator;
            job[minJob].finishTime = job[minJob].beginWorkTime + job[minJob].runTime;
            timeSimulator = job[minJob].finishTime;
            totalTime(minJob);
            calcWeightTotalTime(minJob);
            job[minJob].beenFinished = true;//该作业执行完成
            System.out.println(job[minJob].name + "执行结束...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
        System.out.println("\t\t\t\t SJF调度算法运行结果");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        printWork();
    }

    //计算作业的响应比
    public void calcResponseRate() {
        for(int i = 0;i < job.length;i++) {
            if(job[i].beenFinished == false && job[i].enterSystemTime <= timeSimulator) {
                job[i].responseRate = (timeSimulator - job[i].enterSystemTime + job[i].runTime) * 1.0 / job[i].runTime;
            }
        }
    }

    //计算出最高响应比的作业
    public int findBeatResponseRate() {
        int best = -1;

        //找出第一个没有被执行过的作业
        int i;
        for (i = 0; i < job.length; i++) {
            if (job[i].beenFinished == false && job[i].enterSystemTime <= timeSimulator) {
                best = i;
                break;
            }
        }
        //与第一个未被执行的作业对比，找出响应比最高的
        for (int j = i; j < job.length; j++) {
            if (job[j].beenFinished == true) {
                continue;
            }
            if (job[j].responseRate > job[best].responseRate && job[j].enterSystemTime <= timeSimulator) {
                best = j;
            }
        }
        return best;
    }

    //响应比最高优先算法
    public void HRRF() {
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        System.out.println("响应比最高优先调度算法（HRRF调度算法）");
        initial();//初始化
        int bestJob = -1;
        for (int i = 0; i < job.length; i++) {
            calcResponseRate();
            bestJob = findBeatResponseRate();
            System.out.println(job[bestJob].name + "开始执行...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            job[bestJob].beginWorkTime = timeSimulator;
            job[bestJob].finishTime = job[bestJob].beginWorkTime + job[bestJob].runTime;
            timeSimulator = job[bestJob].finishTime;
            totalTime(bestJob);
            calcWeightTotalTime(bestJob);
            job[bestJob].beenFinished = true;
            System.out.println(job[bestJob].name + "执行结束...");

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
        System.out.println("\t\t\t\t HRRF调度算法运行结果");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printWork();
    }
}

